﻿using System;
using System.Linq;
using NHibernate;
using NHibernate.Linq;

namespace Model
{
    public interface ITransaction : IDisposable
    {
        void Commit();
        void Rollback();
    }

    public class Transaction : ITransaction
    {
        private readonly NHibernate.ITransaction _innerTransaction;

        public Transaction(NHibernate.ITransaction innerTransaction)
        {
            _innerTransaction = innerTransaction;
        }

        public void Commit()
        {
            _innerTransaction.Commit();
        }

        public void Rollback()
        {
            _innerTransaction.Rollback();
        }

        public void Dispose()
        {
            if (_innerTransaction != null)
                _innerTransaction.Dispose();
        }
    }

	public interface IRepository : IDisposable
	{
		void Save<T>(T t);
		void Update<T>(T t);
		IQueryable<T> Query<T>();
	    ITransaction BeginTransaction();
	}

	public class Repository : IRepository
	{
		private readonly ISession _session;

		public Repository(ISession session)
		{
			_session = session;
		}

		public void Save<T>(T t)
		{
			_session.Save(t);
            _session.Flush();
		}

		public void Update<T>(T t)
		{
			_session.Update(t);
            _session.Flush();
		}

		public IQueryable<T> Query<T>()
		{
			return _session.Query<T>();
		}

	    public ITransaction BeginTransaction()
	    {
	        return new Transaction(_session.BeginTransaction());
	    }

	    public void Dispose()
	    {
	        if(_session != null)
                _session.Dispose();
	    }
	}

    public class NonFlushingRepository : IRepository
    {
        private readonly ISession _session;

        public NonFlushingRepository(ISession session)
        {
            _session = session;
        }

        public void Save<T>(T t)
        {
            _session.Save(t);
        }

        public void Update<T>(T t)
        {
            _session.Update(t);
        }

        public IQueryable<T> Query<T>()
        {
            return _session.Query<T>();
        }

        public ITransaction BeginTransaction()
        {
            return new Transaction(_session.BeginTransaction());
        }

        public void Dispose()
        {
            if (_session != null)
                _session.Dispose();
        }
    }
}
